/**
 * 材质管理路由
 */
const express = require('express');
const router = express.Router({ mergeParams: true });
const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');
const { PROJECTS_DIR } = require('../utils/constants');
const { generateId } = require('../utils/helpers');
const { readProjectsIndex } = require('../services/projectService');
const {
    readMaterialConfig,
    writeMaterialConfig,
    deleteMaterialConfig,
    getAllMaterials,
    findMaterialByDisplayName
} = require('../utils/materialConfigHelper');
const {
    syncMaterialTextureReferences,
    removeMaterialTextureReferences
} = require('../utils/textureConfigHelper');

/**
 * 获取项目的材质库列表
 * GET /api/projects/:id/materials
 */
router.get('/', async (req, res) => {
    try {
        const { id } = req.params;
        
        console.log(`\n🎨 [Materials API] 获取材质库列表: project=${id}`);
        
        const index = await readProjectsIndex();
        const projectMeta = index.projects.find(p => p.id === id);
        
        if (!projectMeta) {
            return res.status(404).json({
                success: false,
                error: '项目不存在'
            });
        }
        
        const projectPath = path.join(PROJECTS_DIR, projectMeta.path);
        const materialsDir = path.join(projectPath, 'materials');
        
        // 确保材质库目录存在
        await fs.mkdir(materialsDir, { recursive: true });
        
        // 读取所有材质配置
        const materials = await getAllMaterials(materialsDir);
        
        console.log(`✅ 材质库列表获取成功: ${materials.length} 个材质`);
        
        res.json({
            success: true,
            data: materials
        });
        
    } catch (error) {
        console.error('❌ 获取材质库列表失败:', error);
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

/**
 * 创建新材质
 * POST /api/projects/:id/materials
 * ✅ 新架构：使用 displayName 作为唯一标识
 */
router.post('/', async (req, res) => {
    try {
        const { id } = req.params;
        const { displayName, description, ...materialParams } = req.body;
        
        console.log(`\n🎨 [Materials API] 创建材质: project=${id}, displayName=${displayName}`);
        
        // 验证 displayName
        if (!displayName || displayName.trim() === '') {
            return res.status(400).json({
                success: false,
                error: '材质显示名称不能为空'
            });
        }
        
        const index = await readProjectsIndex();
        const projectMeta = index.projects.find(p => p.id === id);
        
        if (!projectMeta) {
            return res.status(404).json({
                success: false,
                error: '项目不存在'
            });
        }
        
        const projectPath = path.join(PROJECTS_DIR, projectMeta.path);
        const materialsDir = path.join(projectPath, 'materials');
        
        // 确保材质库文件夹存在
        await fs.mkdir(materialsDir, { recursive: true });
        
        // 检查材质是否已存在（按 displayName 匹配）
        const existingMaterial = await findMaterialByDisplayName(materialsDir, displayName);
        
        if (existingMaterial) {
            // 材质已存在，返回现有材质数据
            console.log(`ℹ️ 材质已存在，返回现有材质: ${existingMaterial.displayName}`);
            
            return res.json({
                success: true,
                data: existingMaterial,
                existed: true // 标记这是已存在的材质
            });
        }
        
        // 材质不存在，创建新材质
        const timestamp = new Date().toISOString();
        
        // 创建材质数据（不再有 id 和 name 字段）
        const materialData = {
            displayName: displayName.trim(),
            description: description || '',
            ...materialParams,
            createdAt: timestamp,
            updatedAt: timestamp
        };
        
        // 保存材质配置文件（使用 displayName 作为文件名）
        await writeMaterialConfig(materialsDir, displayName, materialData);
        
        // 🔗 更新贴图引用信息
        const texturesDir = path.join(projectPath, 'textures');
        await syncMaterialTextureReferences(texturesDir, materialData);
        
        console.log(`✅ 材质创建成功: ${displayName}`);
        
        res.json({
            success: true,
            data: materialData,
            existed: false // 标记这是新创建的材质
        });
        
    } catch (error) {
        console.error('❌ 创建材质失败:', error);
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

/**
 * 获取材质详情
 * GET /api/projects/:id/materials/:displayName
 * ✅ 新架构：使用 displayName（URL编码）作为参数
 */
router.get('/:displayName', async (req, res) => {
    try {
        const { id, displayName } = req.params;
        const decodedDisplayName = decodeURIComponent(displayName);
        
        console.log(`\n🎨 [Materials API] 获取材质详情: project=${id}, displayName=${decodedDisplayName}`);
        
        const index = await readProjectsIndex();
        const projectMeta = index.projects.find(p => p.id === id);
        
        if (!projectMeta) {
            return res.status(404).json({
                success: false,
                error: '项目不存在'
            });
        }
        
        const materialsDir = path.join(PROJECTS_DIR, projectMeta.path, 'materials');
        const material = await readMaterialConfig(materialsDir, decodedDisplayName);
        
        if (!material) {
            return res.status(404).json({
                success: false,
                error: '材质不存在'
            });
        }
        
        console.log(`✅ 材质详情获取成功: ${material.displayName}`);
        
        res.json({
            success: true,
            data: material
        });
        
    } catch (error) {
        console.error('❌ 获取材质详情失败:', error);
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

/**
 * 更新材质
 * PUT /api/projects/:id/materials/:displayName
 * ✅ 新架构：使用 displayName 作为参数
 */
router.put('/:displayName', async (req, res) => {
    try {
        const { id, displayName } = req.params;
        const decodedDisplayName = decodeURIComponent(displayName);
        const updateData = req.body;
        
        console.log(`\n🎨 [Materials API] 更新材质: project=${id}, displayName=${decodedDisplayName}`);
        
        // 不允许修改 displayName（因为它是唯一标识）
        if (updateData.displayName && updateData.displayName !== decodedDisplayName) {
            return res.status(400).json({
                success: false,
                error: '不能修改材质的显示名称（displayName是唯一标识）'
            });
        }
        
        const index = await readProjectsIndex();
        const projectMeta = index.projects.find(p => p.id === id);
        
        if (!projectMeta) {
            return res.status(404).json({
                success: false,
                error: '项目不存在'
            });
        }
        
        const projectPath = path.join(PROJECTS_DIR, projectMeta.path);
        const materialsDir = path.join(projectPath, 'materials');
        const oldMaterial = await readMaterialConfig(materialsDir, decodedDisplayName);
        
        if (!oldMaterial) {
            return res.status(404).json({
                success: false,
                error: '材质不存在'
            });
        }
        
        // 更新材质数据
        const material = { ...oldMaterial };
        Object.assign(material, updateData);
        material.displayName = decodedDisplayName; // 确保 displayName 不被修改
        
        // 保存材质配置
        await writeMaterialConfig(materialsDir, decodedDisplayName, material);
        
        // 🔗 同步贴图引用信息（对比新旧材质数据）
        const texturesDir = path.join(projectPath, 'textures');
        await syncMaterialTextureReferences(texturesDir, material, oldMaterial);
        
        console.log(`✅ 材质更新成功: ${material.displayName}`);
        
        res.json({
            success: true,
            data: material
        });
        
    } catch (error) {
        console.error('❌ 更新材质失败:', error);
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

/**
 * 删除材质
 * DELETE /api/projects/:id/materials/:displayName
 * ✅ 新架构：使用 displayName 作为参数
 */
router.delete('/:displayName', async (req, res) => {
    try {
        const { id, displayName } = req.params;
        const decodedDisplayName = decodeURIComponent(displayName);
        
        console.log(`\n🎨 [Materials API] 删除材质: project=${id}, displayName=${decodedDisplayName}`);
        
        const index = await readProjectsIndex();
        const projectMeta = index.projects.find(p => p.id === id);
        
        if (!projectMeta) {
            return res.status(404).json({
                success: false,
                error: '项目不存在'
            });
        }
        
        const projectPath = path.join(PROJECTS_DIR, projectMeta.path);
        const materialsDir = path.join(projectPath, 'materials');
        const material = await readMaterialConfig(materialsDir, decodedDisplayName);
        
        if (!material) {
            return res.status(404).json({
                success: false,
                error: '材质不存在'
            });
        }
        
        // 检查材质是否被引用
        if (material.usedByMeshes && material.usedByMeshes.length > 0) {
            console.log(`⚠️ 材质被引用，无法删除: ${decodedDisplayName}, 引用数: ${material.usedByMeshes.length}`);
            return res.status(400).json({
                success: false,
                error: '该材质正在被使用，无法删除',
                usedByMeshes: material.usedByMeshes
            });
        }
        
        // 🔗 移除所有贴图引用
        const texturesDir = path.join(projectPath, 'textures');
        await removeMaterialTextureReferences(texturesDir, material);
        
        // 删除材质配置文件
        await deleteMaterialConfig(materialsDir, decodedDisplayName);
        
        console.log(`✅ 材质删除成功: ${material.displayName}`);
        
        res.json({
            success: true,
            message: '材质删除成功'
        });
        
    } catch (error) {
        console.error('❌ 删除材质失败:', error);
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

/**
 * 重命名材质
 * POST /api/projects/:id/materials/:displayName/rename
 * ✅ 新架构：重命名需要删除旧文件并创建新文件
 */
router.post('/:displayName/rename', async (req, res) => {
    try {
        const { id, displayName } = req.params;
        const decodedDisplayName = decodeURIComponent(displayName);
        const { newDisplayName } = req.body;
        
        if (!newDisplayName || newDisplayName.trim() === '') {
            return res.status(400).json({
                success: false,
                error: '新显示名称不能为空'
            });
        }
        
        const index = await readProjectsIndex();
        const projectMeta = index.projects.find(p => p.id === id);
        
        if (!projectMeta) {
            return res.status(404).json({
                success: false,
                error: '项目不存在'
            });
        }
        
        const materialsDir = path.join(PROJECTS_DIR, projectMeta.path, 'materials');
        const material = await readMaterialConfig(materialsDir, decodedDisplayName);
        
        if (!material) {
            return res.status(404).json({
                success: false,
                error: '材质不存在'
            });
        }
        
        // 检查新名称是否已存在
        const existingMaterial = await readMaterialConfig(materialsDir, newDisplayName);
        if (existingMaterial) {
            return res.status(400).json({
                success: false,
                error: '新名称已被其他材质使用'
            });
        }
        
        // 更新 displayName
        material.displayName = newDisplayName.trim();
        
        // 删除旧文件
        await deleteMaterialConfig(materialsDir, decodedDisplayName);
        
        // 用新名称保存材质配置
        await writeMaterialConfig(materialsDir, newDisplayName, material);
        
        console.log(`✅ 材质重命名成功: ${decodedDisplayName} → ${newDisplayName}`);
        
        res.json({
            success: true,
            data: material
        });
        
    } catch (error) {
        console.error('❌ 材质重命名失败:', error);
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

/**
 * 更新材质的节点引用（添加或删除）- 支持批量更新
 * POST /api/projects/:id/materials/:displayName/node-references
 * ✅ 新架构：使用 displayName 作为参数
 * Body: { 
 *   sceneId, 
 *   nodeId, 
 *   action: 'add' | 'remove',
 *   meshes: [{ meshId, meshName }, ...] 或 单个 { meshId, meshName }
 * }
 */
router.post('/:displayName/node-references', async (req, res) => {
    try {
        const { id, displayName } = req.params;
        const decodedDisplayName = decodeURIComponent(displayName);
        const { sceneId, nodeId, meshId, meshName, meshes, action } = req.body;
        
        console.log(`\n📌 [Material References] 更新材质引用: material=${decodedDisplayName}, scene=${sceneId}, node=${nodeId}, action=${action}`);
        
        if (!sceneId || !nodeId || !action) {
            return res.status(400).json({
                success: false,
                error: '缺少必要参数: sceneId, nodeId, action'
            });
        }
        
        if (action !== 'add' && action !== 'remove') {
            return res.status(400).json({
                success: false,
                error: 'action 必须是 "add" 或 "remove"'
            });
        }
        
        // 步骤1: 读取项目索引
        const index = await readProjectsIndex();
        const projectMeta = index.projects.find(p => p.id === id);
        
        if (!projectMeta) {
            return res.status(404).json({
                success: false,
                error: '项目不存在'
            });
        }
        
        // ⏱️ 步骤2: 读取材质文件
        const materialsDir = path.join(PROJECTS_DIR, projectMeta.path, 'materials');
        const material = await readMaterialConfig(materialsDir, decodedDisplayName);
        
        if (!material) {
            return res.status(404).json({
                success: false,
                error: '材质不存在'
            });
        }
        
        // 确保 usedByMeshes 数组存在
        if (!material.usedByMeshes) {
            material.usedByMeshes = [];
        }
        
        // ⚡ 支持批量更新：处理 meshes 数组或单个 mesh
        const meshList = meshes || (meshId ? [{ meshId, meshName }] : []);
        
        if (meshList.length === 0) {
            return res.status(400).json({
                success: false,
                error: '缺少 mesh 信息: 需要提供 meshId 或 meshes 数组'
            });
        }
        
        let addedCount = 0;
        let skippedCount = 0;
        let removedCount = 0;
        
        if (action === 'add') {
            // 批量添加引用
            for (const mesh of meshList) {
                const exists = material.usedByMeshes.some(
                    ref => ref.sceneId === sceneId && ref.nodeId === nodeId && ref.meshId === mesh.meshId
                );
                
                if (!exists) {
                    material.usedByMeshes.push({
                        sceneId: sceneId,
                        nodeId: nodeId,
                        meshId: mesh.meshId,
                        meshName: mesh.meshName || mesh.meshId,
                        addedAt: new Date().toISOString()
                    });
                    addedCount++;
                } else {
                    skippedCount++;
                }
            }
        } else if (action === 'remove') {
            // 批量移除引用
            for (const mesh of meshList) {
                const beforeLength = material.usedByMeshes.length;
                
                // ⭐ 修复：同时匹配 meshId 和 meshName，因为数据格式可能不一致
                // 有些旧数据 meshId 是 UUID，有些新数据 meshId 是 meshName
                material.usedByMeshes = material.usedByMeshes.filter(ref => {
                    // 必须sceneId和nodeId都匹配
                    if (ref.sceneId !== sceneId || ref.nodeId !== nodeId) {
                        return true; // 保留
                    }
                    
                    // meshId 或 meshName 任意一个匹配就删除
                    const meshIdMatch = ref.meshId === mesh.meshId;
                    const meshNameMatch = ref.meshName === mesh.meshId || ref.meshName === mesh.meshName;
                    
                    return !(meshIdMatch || meshNameMatch); // 匹配就删除（返回false）
                });
                
                if (material.usedByMeshes.length < beforeLength) {
                    removedCount++;
                }
            }
        }
        
        if (addedCount > 0 || removedCount > 0) {
            await writeMaterialConfig(materialsDir, decodedDisplayName, material);
            console.log(`💾 [Material References] 保存成功: 添加=${addedCount}, 移除=${removedCount}, 跳过=${skippedCount}`);
        }
        
        res.json({
            success: true,
            data: {
                displayName: decodedDisplayName,
                usedByMeshes: material.usedByMeshes,
                stats: {
                    added: addedCount,
                    removed: removedCount,
                    skipped: skippedCount
                }
            }
        });
        
    } catch (error) {
        console.error('❌ [Material References] 更新材质引用失败:', error);
        res.status(500).json({
            success: false,
            error: error.message
        });
    }
});

module.exports = router;

